package com.arvato.common.https;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.arvato.minipro.bean.bean_do.wx.PublicAccountFansDo;
import com.arvato.minipro.bean.bean_dto.common.Query;
import com.arvato.minipro.bean.bean_dto.common.Result;
import com.arvato.minipro.bean.bean_vo.wx.PublicAccountFansVo;
import com.arvato.common.config_bean.WxPublicAccountConfig;
import com.arvato.common.redis.RedisUtil;
import com.arvato.common.util.DateFormatUtil;
import com.arvato.common.util.JsonUtil;
import com.arvato.minipro.service.wx.PublicAccountFansService;
/**
 * 
 * @author: smallking
 * 
 * @Descibe:微信公众号和微信服务器请求交互的工具类
 * 
 * @Date: 2018年8月2日  下午2:45:31
 */
@Component
public class WxPublicAccountRequestUtil {
	private Logger logger = LoggerFactory.getLogger(WxPublicAccountRequestUtil.class);
	
	@Autowired
	private RedisUtil redisUtil;
	
	@Autowired
	private JsonUtil jsonUtil;
	
	@Autowired
	private PublicAccountFansService publicAccountFansService;
	
	/**
	 * 获取公众号的AccessToken
	 * @return
	 */
	public synchronized Result getPublicAccountAccessToken() {
		Result result = new Result(false);
		String accessToken = redisUtil.get("public_account_access_token");
		// 如果当前缓存里面有public_account_access_token 直接返回
		if(accessToken != null) {
			result.setResult(true);
			result.setData(accessToken);
			logger.info("redis缓存中存在公众号的令牌public_account_access_token");
			return result;
		}
		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
		url = String.format(url, WxPublicAccountConfig.WX_PUBLIC_ACCOUNT_APPID, WxPublicAccountConfig.WX_APPID_SECRET);
		String respJsonStr = HttpsUtil.httpsRequest(url, "GET", null);
		logger.info("请求微信公众号access_token返回的字符串:" + respJsonStr);
		Map<String, Object> map = jsonUtil.str2Map(respJsonStr);
		if(map != null && map.get("access_token") != null) {
			String token = map.get("access_token") + "";
			redisUtil.set("public_account_access_token", token.toString(), 7000);
			result.setResult(true);
			result.setData(token.toString());
			logger.info("获取微信公众号的AccessToken令牌成功");
			return result;
		}
		return result;
	}
	
	/**
	 * 获取拉起会员卡开卡组件所需的参数
	 * @param cardId
	 * @return
	 */
	public Result getMemberCardParam(String cardId) {
		Result result = getPublicAccountAccessToken();
		String url = "https://api.weixin.qq.com/card/membercard/activate/geturl?access_token=" + result.getData();
		// 请求参数map
		Map<String, Object> paramJson = new HashMap<String, Object>();
	    paramJson.put("card_id", cardId);
	    String jsonStr = jsonUtil.obj2String(paramJson);
	    System.out.println("json参数" + jsonStr);
		String respJsonStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("请求开卡信息的返回值:" + respJsonStr);
		Map<String, Object> map = jsonUtil.str2Map(respJsonStr);
		if(map != null && map.get("url") != null) {
			String cardUrl = map.get("url") + "";
			result.setData(cardUrl);
		}
		return result;
	}
	
	/**
	 * 设置会员卡的开卡字段
	 * @param cardId
	 * @return
	 */
	public Result setCardColumn(String cardId) {
		Result result = getPublicAccountAccessToken();
		String url = "https://api.weixin.qq.com/card/membercard/activateuserform/set?access_token=" + result.getData();
		Map<String, Object> paramMap = new HashMap<String, Object>();
		Map<String, Object> requiredFormMap = new HashMap<String, Object>();
		List<String> fieldList = new ArrayList<String>();
		paramMap.put("card_id", cardId);
		paramMap.put("required_form", requiredFormMap);
		requiredFormMap.put("can_modify", false);
		requiredFormMap.put("common_field_id_list", fieldList);
		fieldList.add("USER_FORM_INFO_FLAG_MOBILE");
		fieldList.add("USER_FORM_INFO_FLAG_NAME");
	    String jsonStr = jsonUtil.obj2String(paramMap);
	    System.out.println("请求设置开卡字段的url" + url + "json参数" + jsonStr);
		String respJsonStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("请求设置开卡字段的返回值:" + respJsonStr);
		Map<String, Object> map = jsonUtil.str2Map(respJsonStr);
		result.setData(map);
		return result;
	}
	
	/**
	 * 设置会员卡为跳转型开卡
	 * @param cardId
	 * @return
	 */
	public Result setCardJump(String cardId) {
		Result result = getPublicAccountAccessToken();
		String url = "https://api.weixin.qq.com/card/update?access_token=" + result.getData();
		// 请求参数map 会员卡是个非常复杂的json
		Map<String, Object> paramMap = new HashMap<String, Object>();
		Map<String, Object> memberCardMap = new HashMap<String, Object>();
		paramMap.put("card_id", cardId);
		paramMap.put("member_card", memberCardMap);
		memberCardMap.put("wx_activate", true);
		memberCardMap.put("wx_activate_after_submit", true);
		memberCardMap.put("wx_activate_after_submit_url", "minipro.arvatocrm.cn/arvato/card_callback.html");
	    String jsonStr = jsonUtil.obj2String(paramMap);
	    System.out.println("json参数" + jsonStr);
		String respJsonStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("请求设置会员卡为跳转型开卡的返回值:" + respJsonStr);
		Map<String, Object> map = jsonUtil.str2Map(respJsonStr);
		if(map != null && "0".equals(map.get("errcode") + "")) {
			result.setData(map);
		}
		return result;
	}
	
	/**
	 * 设置公众号会员卡点击跳转的小程序
	 * 其他的一些修改参数 请参展微信公众平台文档
	 * 看文档要有灵性，要会看 还要会根据经验来猜
	 * @param cardId 
	 * @param miniproId
	 * @return
	 */
	public Result setMemberToMinipro(String cardId, String miniproId) {
		Result result = getPublicAccountAccessToken();
		String url = "https://api.weixin.qq.com/card/update?access_token=" + result.getData();
		// 请求参数map 会员卡是个非常复杂的json
		Map<String, Object> paramMap = new HashMap<String, Object>();
		Map<String, Object> memberCardMap = new HashMap<String, Object>();
		Map<String, Object> baseInfoMap = new HashMap<String, Object>();
		paramMap.put("card_id", cardId);
		paramMap.put("member_card", memberCardMap);
		memberCardMap.put("base_info", baseInfoMap);
        baseInfoMap.put("custom_url_name", "Arvato");
        baseInfoMap.put("custom_url_sub_title", "小程序");
		baseInfoMap.put("custom_app_brand_user_name", miniproId + "@app");
		baseInfoMap.put("custom_app_brand_pass", "/pages/index/index");
	    String jsonStr = jsonUtil.obj2String(paramMap);
	    System.out.println("json参数" + jsonStr);
		String respJsonStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("请求设置卡卷点击跳转到小程序的返回值:" + respJsonStr);
		Map<String, Object> map = jsonUtil.str2Map(respJsonStr);
		if(map != null && "0".equals(map.get("errcode") + "")) {
			result.setData(map);
		}
		return result;
	}
	
	/**
	 * 激活会员卡
	 * @param code
	 * @return
	 */
	public Result activeCard(String code) {
		Result result = getPublicAccountAccessToken();
		String url = "https://api.weixin.qq.com/card/membercard/activate?access_token=" + result.getData();
		// 请求参数map 会员卡是个非常复杂的json
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("membership_number", code);
		paramMap.put("code", code);
	    String jsonStr = jsonUtil.obj2String(paramMap);
	    System.out.println("json参数" + jsonStr);
		String respJsonStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("请求设置激活会员卡的返回值:" + respJsonStr);
		Map<String, Object> map = jsonUtil.str2Map(respJsonStr);
		if(map != null && "0".equals(map.get("errcode") + "")) {
			result.setData(map);
		}
		return result;
	}
	
	/**
	 * 查询一个openid对应card下的code
	 * @param openId
	 * @return
	 */
	public Result getCardCode(String openId, String cardId) {
		Result result = getPublicAccountAccessToken();
		result.setResult(false);
		String url = "https://api.weixin.qq.com/card/user/getcardlist?access_token=" + result.getData();
		// 请求参数map 会员卡是个非常复杂的json
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("openid", openId);
		paramMap.put("card_id", cardId);
	    String jsonStr = jsonUtil.obj2String(paramMap);
	    logger.info("请求会员卡code的json参数" + jsonStr + "----url" + url);
		String respJsonStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("请求获取用户已领取的卡券code:" + respJsonStr);
		Map<String, Object> map = jsonUtil.str2Map(respJsonStr);
		if(map != null && "0".equals(map.get("errcode") + "")) {
			@SuppressWarnings("unchecked")
			List<Map<String, String>> cardList = (List<Map<String, String>>)map.get("card_list");
			// 因为目前就一个会员卡 所以直接从cardList中得到该用户的会员卡的code
			String code = cardList.get(0).get("code");
			logger.info("会员卡的code:" + code);
			result.setResult(true);
			result.setData(code);
		}
		return result;
	}
	
	/**
	 * 根据cardId和code查询一个会员的信息详情
	 * @param cardId 
	 * @param openId
	 * @return
	 */
	public Result getMemberInfo(String cardId, String code) {
		Result result = getPublicAccountAccessToken();
		result.setResult(false);
		// 根据code查询会员卡详情
		String url = "https://api.weixin.qq.com/card/membercard/userinfo/get?access_token=" + result.getData();
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("code", code);
	    String jsonStr = jsonUtil.obj2String(paramMap);
	    logger.info("拉取会员信息的参数" + jsonStr + "----url" + url);
		String memberInfoStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("拉取会员信息的返回值:" + memberInfoStr);
		Map<String, Object> memberInfoMap = jsonUtil.str2Map(memberInfoStr);
		if(memberInfoMap != null && "0".equals(memberInfoMap.get("errcode") + "")) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("bonus", memberInfoMap.get("bonus") + "");
			map.put("code", code);
			result.setResult(true);
			result.setData(map);
		}
		return result;
	}
	
	/**
	 * 根据cardId和code修改一个会员卡的积分
	 * @param cardId  
	 * @param code 卡片的code
	 * @param bonus 积分总值
	 * @param addBonus 本次积分变动值，传负数代表减少
	 * @param recordBonus 商家自定义积分消耗记录，不超过14个汉字
	 * @return
	 */
	public Result updateBonus(String cardId, String code, int bonus, int addBonus, String recordBonus) {
		Result result = getPublicAccountAccessToken();
		result.setResult(false);
		// 根据cardId 和 code修改会员卡积分
		String url = "https://api.weixin.qq.com/card/membercard/updateuser?access_token=" + result.getData();
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("card_id", cardId);
		paramMap.put("code", code);
		paramMap.put("bonus", bonus);
		paramMap.put("add_bonus", addBonus);
		paramMap.put("record_bonus", recordBonus);
	    String jsonStr = jsonUtil.obj2String(paramMap);
	    logger.info("修改会员积分的参数" + jsonStr + "----url：" + url);
		String responseStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("修改会员积分的返回值:" + responseStr);
		Map<String, Object> map = jsonUtil.str2Map(responseStr);
		if(map != null && "0".equals(map.get("errcode") + "")) {
			result.setResult(true);
		}
		return result;
	}
	
	/**
	 * 查看核销卡卷的详情
	 * @param code
	 * @return
	 */
	public Result consumeCodeInfo(String code) {
		String accessToken = "";
		Result result = getPublicAccountAccessToken();
		if(result.getCode() == 500) {
			return result;
		}
		result.setResult(false);
		accessToken = result.getData() + "";
		String url = "https://api.weixin.qq.com/card/code/get?access_token=" + accessToken;
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("code", code);
		String jsonStr = jsonUtil.obj2String(paramMap);
		logger.info("查看卡卷核销信息的参数" + jsonStr + "----url：" + url);
		String responseStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("查看卡卷核销信息的返回值:" + responseStr);
		Map<String, Object> map = jsonUtil.str2Map(responseStr);
		if(map != null && "0".equals(map.get("errcode") + "")) {
			result.setResult(true);
			result.setData(map);
		}
		return result;
	}
	
	/**
	 * 核销卡卷
	 * @param code
	 * @return
	 */
	public Result consumeCard(String code) {
		String accessToken = "";
		Result result = getPublicAccountAccessToken();
		if(result.getCode() == 500) {
			return result;
		}
		result.setResult(false);
		accessToken = result.getData() + "";
		String url = "https://api.weixin.qq.com/card/code/consume?access_token=" + accessToken;
		Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("code", code);
		paramMap.put("card_id", "ppY5mwRZ36EzMHulz6rKerKtlzBE");
		String jsonStr = jsonUtil.obj2String(paramMap);
	    logger.info("核销卡卷的参数" + jsonStr + "----url：" + url);
		String responseStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("核销卡卷的返回值:" + responseStr);
		Map<String, Object> map = jsonUtil.str2Map(responseStr);
		if(map != null && "0".equals(map.get("errcode") + "")) {
			result.setResult(true);
			result.setMsg("核销成功" + code);
		}
		return result;
	}

	/**
	 * 得到欧唯特公众号的所有粉丝，并且将其对应的openid unionid存储到数据库
	 * @return
	 */
	public Result getFansUsers() {
		Result result = getPublicAccountAccessToken();
		String url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + result.getData();
		
		String respJsonStr = HttpsUtil.httpsRequest(url, "GET", null);
		logger.info("请求公众号所有粉丝的openid和unoinid并且存储到数据库的url" + url);
		logger.info("请求公众号所有粉丝的openid和unoinid并且存储到数据库" + respJsonStr);
		Map<String, Object> map = jsonUtil.str2Map(respJsonStr);
		if(map != null && Integer.valueOf(map.get("count") + "") >= 2) {
			@SuppressWarnings("unchecked")
			Map<String, List<String>> fansMap = (Map<String, List<String>>)map.get("data");
			List<String> fansList = fansMap.get("openid");
			// 将fansList和数据库中的用户粉丝账号做对比。不存在数据库的，执行插入
			for(String openId : fansList) {
				saveUnionId(openId, 1);
			}
		}
		return result;
	}
	
	/**
	 * 根据openId获取unionId并且存储
	 * @param openId 公众号的openid
	 * @param type 1是根据粉丝列表来查询的 
	 * 				2是根据开卡成功后，回调里面的openid参数来查询的
	 * 				
	 * @return
	 */
	public Result saveUnionId(String openId, Integer type) {
		Query query = new Query();
		query.put("openId", openId);
		List<PublicAccountFansVo> openIdList = publicAccountFansService.listByQuery(query);
		if(openIdList != null && openIdList.size() >= 1) {
			// 如果当前粉丝已经存在 就不用再继续存储了
		    logger.info("当前粉丝：" + openId + "已存在");
		    Result result = new Result(true);
		    result.setData("当前粉丝：" + openId + "已存在");
			return result;
		}else {
			Result result = getPublicAccountAccessToken();
			// 根据openId 获取unionId插入数据库
			String userInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + result.getData() + "&openid=" + openId + "&lang=zh_CN";
			String userInfoStr = HttpsUtil.httpsRequest(userInfoUrl, "GET", null);
			logger.info("根据openid" + openId + "换取的unionid返回值" + userInfoStr);
			Map<String, Object> userInfoMap = jsonUtil.str2Map(userInfoStr);
			Object unionId = userInfoMap.get("unionid");
			if(unionId != null) {
				// 执行数据库插入
				PublicAccountFansDo fansDo = new PublicAccountFansDo();
				fansDo.setAppId("wx9522dba2074c18cf");
				fansDo.setOpenId(openId);
				fansDo.setUnionId(unionId + "");
				if(1 == type) {
					fansDo.setCreateTime(new Date());
				}else {
					fansDo.setCreateTime(DateFormatUtil.str2Date("2001-01-01", null));
				}
				int row = publicAccountFansService.insert(fansDo);
				if(row == 1) {
					result.setData("新增成功" + fansDo.toString());
					return result;
				}
			}
		}
		return null;
	}
	
	
	/**
	 * 得到所有的模板消息
	 * @return
	 */
	public Result templateMsgList() {
		Result result = getPublicAccountAccessToken();
		String url = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=" + result.getData();
		String respJsonStr = HttpsUtil.httpsRequest(url, "GET", null);
		logger.info("获取公众号的所有模板消息列表：" + respJsonStr);
		result.setData(respJsonStr);
		return result;
	}	
	
	/**
	 * 发送模板消息
	 * @return
	 */
	public Result sendTemplateMsg(String templateId, String openId, String clickUrl) {
		Result result = getPublicAccountAccessToken();
		String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + result.getData();
		// 请求参数map
		Map<String, Object> paramJson = new HashMap<String, Object>();
		Map<String, Object> dataMap = new HashMap<String, Object>();
		Map<String, Object> keyword1 = new HashMap<String, Object>();
		Map<String, Object> keyword2 = new HashMap<String, Object>();
		Map<String, Object> keyword3 = new HashMap<String, Object>();
		Map<String, Object> keyword4 = new HashMap<String, Object>();
		Map<String, Object> keyword5 = new HashMap<String, Object>();
	    paramJson.put("touser", openId);
	    paramJson.put("template_id", templateId);
	    paramJson.put("url", clickUrl);
	    paramJson.put("data", dataMap);
	    keyword1.put("value", "你的专属BC已经上线，加他为好友吧");
	    keyword2.put("value", "test");
	    keyword3.put("value", "test");
	    keyword4.put("value", clickUrl);
	    keyword5.put("value", "记得长按二维码");
	    dataMap.put("first", keyword1);
	    dataMap.put("keyword1", keyword2);
	    dataMap.put("keyword2", keyword3);
	    dataMap.put("keyword3", keyword4);
	    dataMap.put("remark", keyword5);
	    String jsonStr = jsonUtil.obj2String(paramJson);
	    System.out.println("json参数" + jsonStr);
		String respJsonStr = HttpsUtil.httpsRequest(url, "POST", jsonStr);
		logger.info("发送模板消息" + respJsonStr);
		result.setData(respJsonStr);
		return result;
	}	
	
}
